package lumingweihua.future.cn.lumingweihua.network;

import android.text.TextUtils;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.zhusx.core.debug.LogUtil;
import com.zhusx.core.imp.OnCycleListenerImp;
import com.zhusx.core.network.Lib_BaseRequestData;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import lumingweihua.future.cn.lumingweihua.AppApplication;
import lumingweihua.future.cn.lumingweihua.ui.BaseAppFragment;
import lumingweihua.future.cn.lumingweihua.ui.BaseCompatActivity;

/**
 * Created by z1986 on 2018/3/18.
 */

public abstract class BaseLoadData<Id, T> extends Lib_BaseRequestData<Id, T, Object, JSONResult<T>> {
    private static RequestQueue mQueue;
    private int hashCode;

    public BaseLoadData(Id id, BaseCompatActivity activity) {
        super(id);
        if (mQueue == null) {
            mQueue = Volley.newRequestQueue(activity);
            mQueue.start();
        }
        hashCode = hashCode();
        activity._addOnCycleListener(new OnCycleListenerImp() {
            @Override
            public void onDestroy() {
                _cancelLoadData();
            }
        });
    }

    public BaseLoadData(Id id, BaseAppFragment activity) {
        super(id);
        if (mQueue == null) {
            mQueue = Volley.newRequestQueue(activity.getContext());
            mQueue.start();
        }
        hashCode = hashCode();
        activity._addOnCycleListener(new OnCycleListenerImp() {
            @Override
            public void onDestroy() {
                _cancelLoadData();
            }
        });
    }

    @Override
    public void _cancelLoadData() {
        super._cancelLoadData();
        mQueue.cancelAll(new RequestQueue.RequestFilter() {
            @Override
            public boolean apply(Request<?> request) {
                return ((int) request.getTag()) == hashCode;
            }
        });
    }

    abstract RequestParam getHttpParams(Id id, Object... objects) throws JSONException;

    @Override
    protected void __requestProtocol(final Id id, Object... objects) {
        try {
            final RequestParam param = getHttpParams(id, objects);
            StringRequest stringRequest = new StringRequest(param.method, param.url, new Response.Listener<String>() {

                //正确接收数据回调
                @Override
                public void onResponse(String s) {
                    String message = "";
                    if (LogUtil.DEBUG) {
                        if (TextUtils.isEmpty(s)) {
                            LogUtil.e("无数据返回");
                            _onError("无数据返回");
                            return;
                        } else {
                            LogUtil.e(String.valueOf(id) + "->" + s);
                        }
                    }
                    try {
                        JSONObject jsonObject = new JSONObject(s);
                        if (jsonObject.getInt("error") == 0) {
                            JSONResult<T> result = new JSONResult<>();
                            if (param.returnClass == Void.class) {
                                //什么都不做
                            } else if (param.returnClass == String.class) {
                                result.data = (T) jsonObject.getString("info");
                            } else {
                                String info = jsonObject.getString("info");
                                if (param.isList) {
                                    if (jsonObject.isNull("info")) {
                                        result.data = (T) new ArrayList();
                                    } else {
                                        result.data = (T) fromJsonArray(info, param.returnClass);
                                        if (result.data == null) {
                                            result.data = (T) new ArrayList();
                                        }
                                    }
                                } else {
                                    if ("[]".equals(info)) {
                                        try {
                                            Toast.makeText(AppApplication.getInstance(), "JSON对象格式PHP返回[]", Toast.LENGTH_SHORT).show();
                                            result.data = (T) param.returnClass.newInstance();
                                        } catch (InstantiationException e) {
                                            e.printStackTrace();
                                        } catch (IllegalAccessException e) {
                                            e.printStackTrace();
                                        }
                                        //php 空類型
                                    } else {
                                        if (jsonObject.isNull("info")) {
                                            try {
                                                result.data = (T) param.returnClass.newInstance();
                                            } catch (InstantiationException e) {
                                                e.printStackTrace();
                                            } catch (IllegalAccessException e) {
                                                e.printStackTrace();
                                            }
                                        } else {
                                            result.data = fromJsonObject(info, (Class<T>) param.returnClass);
                                        }
                                    }
                                }
                            }
                            _onComplete(result);
                        } else {
                            if (jsonObject.has("info")) {
                                message = jsonObject.getString("info");
                            }
                            _onError(message);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                        _onError("服务器返回数据格式错误");
                    } catch (JsonSyntaxException e) {
                        e.printStackTrace();
                        _onError("服务器返回数据格式错误");
                    } catch (Exception e) {
                        e.printStackTrace();
                        _onError(message);
                    }
                }
            }, new Response.ErrorListener() {//异常后的监听数据
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    LogUtil.e(volleyError.getMessage());
                    _onError("");
                }
            }) {
                @Override
                protected Map<String, String> getParams() {
                    return param.map;
                }
            };
            //将get请求添加到队列中
            _onStart();
            stringRequest.setTag(hashCode);
            LogUtil.e(String.valueOf(id) + "->" + String.valueOf(param.map));
            mQueue.add(stringRequest);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    Gson GSON = new Gson();

    public <T> T fromJsonObject(String reader, Class<T> cls) {
        return GSON.fromJson(reader, cls);
    }

    public <C> List<C> fromJsonArray(String json, Class<C> clazz) {
        Type type = new TypeToken<ArrayList<JsonObject>>() {
        }.getType();
        List<JsonObject> jsonObjects = GSON.fromJson(json, type);
        List<C> arrayList = new ArrayList<>();
        for (JsonObject jsonObject : jsonObjects) {
            arrayList.add(GSON.fromJson(jsonObject, clazz));
        }
        return arrayList;
    }

    public String valueOf(Object o) {
        if (o == null) {
            return "";
        }
        return String.valueOf(o);
    }
}
